package com.zhaosc.elasticsearch;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpHost;
import org.apache.log4j.Logger;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse.Result;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;

import com.google.common.collect.Lists;
/**
 * https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.5/java-rest-high-document-index.html
 * @author zhaosc
 *
 */
public class ElasticSearchUtils {

	private static final Logger logger = Logger.getLogger(ElasticSearchUtils.class);

	public static RestHighLevelClient getClient() {

		RestHighLevelClient client = new RestHighLevelClient(
				RestClient.builder(new HttpHost("47.95.7.17", 9200, "http")));
		return client;
	}

	public static boolean index(String index, Map<String, String> source) {
		RestHighLevelClient client = getClient();
		IndexRequest indexRequest = new IndexRequest(index);
		// 第一种方式map
		indexRequest.source(source);
		RequestOptions options = RequestOptions.DEFAULT;
		

		try {
			IndexResponse indexResponse = client.index(indexRequest, options);
			Result result = indexResponse.getResult();
			logger.info(result);
			return Result.CREATED == result;
		} catch (IOException e) {
			logger.error(e);
		}
		return false;
	}

	public static void indexAsync(String index, Map<String, String> source) {
		RestHighLevelClient client = getClient();
		IndexRequest indexRequest = new IndexRequest(index);
		indexRequest.source(source);
		RequestOptions options = RequestOptions.DEFAULT;
		client.indexAsync(indexRequest, options, new ActionListener<IndexResponse>() {

			@Override
			public void onResponse(IndexResponse response) {
				Result result = response.getResult();
				logger.info("*******" + result);
			}

			@Override
			public void onFailure(Exception e) {
				logger.error(e);
			}
		});
	}
	
	public static void delete(String index,String id) {
		RestHighLevelClient client = getClient();
		DeleteRequest deleteRequest=new DeleteRequest(index);
		deleteRequest.id(id);
		RequestOptions options = RequestOptions.DEFAULT;
		try {
			DeleteResponse response=client.delete(deleteRequest, options);
			if(RestStatus.OK==response.status()) {
				logger.info("***success***");
			}
		} catch (IOException e) {
			logger.error(e);
		}
	}
	
	public static void delete2(String index,String id) {
		RestHighLevelClient client = getClient();
		DeleteRequest deleteRequest=new DeleteRequest(index);
		deleteRequest.id(id);
		RequestOptions options = RequestOptions.DEFAULT;
		DeleteByQueryRequest deleteByQueryRequest=new DeleteByQueryRequest(index);
		//deleteByQueryRequest.setQuery(query);
		try {
			client.deleteByQuery(deleteByQueryRequest, options);
		} catch (IOException e) {
			logger.error(e);
		}
	}
	
	@Test
	public static void update(String index,String id,Map<String, Object> source) {
		RestHighLevelClient client = getClient();
		UpdateRequest updateRequest = new UpdateRequest();
		updateRequest.index(index);
		updateRequest.id(id);
		updateRequest.doc(toArgs(source));
		RequestOptions options = RequestOptions.DEFAULT;
		try {
			UpdateResponse updateResponse=client.update(updateRequest, options);
			if(RestStatus.OK==updateResponse.status()) {
				logger.error("****success****");
			}
		} catch (IOException e) {
			logger.error(e);
		}
		
		
	}

	public static void search(String index, int start, int size) {
		RestHighLevelClient client = getClient();
		SearchRequest searchRequest = new SearchRequest(index);
		searchRequest.searchType(SearchType.DEFAULT);
		SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
		sourceBuilder.from(start);
		sourceBuilder.size(size);
		sourceBuilder.query(QueryBuilders.matchQuery("xingming", "zhaosd"));
		// 指定排序
		sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
		sourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC));

		// 高亮设置
		HighlightBuilder highlightBuilder = new HighlightBuilder();
		HighlightBuilder.Field highlight = new HighlightBuilder.Field("xingming");
		highlight.highlighterType("unified");
		highlight.preTags("<red>");
		highlight.postTags("</red>");
		highlightBuilder.field(highlight);
		sourceBuilder.highlighter(highlightBuilder);
		searchRequest.source(sourceBuilder);
		RequestOptions options = RequestOptions.DEFAULT;
		try {
			SearchResponse response = client.search(searchRequest, options);
			if (response.status() == RestStatus.OK) {
				SearchHits hits = response.getHits();

				SearchHit[] searchHits = hits.getHits();
				for (SearchHit hit : searchHits) {

					String text = hit.getSourceAsString(); // 取成json串
        			logger.info(text);
				}
			}
		} catch (IOException e) {
			logger.error(e);
		}

	}

	public static void searchAsync(String index, Map<String, String> source) {
		RestHighLevelClient cliet = getClient();
		SearchRequest searchRequest = new SearchRequest(index);
		RequestOptions options = RequestOptions.DEFAULT;
		cliet.searchAsync(searchRequest, options, new ActionListener<SearchResponse>() {

			@Override
			public void onResponse(SearchResponse response) {
				logger.info(response);
			}

			@Override
			public void onFailure(Exception e) {
				e.printStackTrace();
			}
		});

	}
	
	 static Object[] toArgs(Map<String, Object> data) {
	      List<Object> args = Lists.newArrayList();
	      if (data==null) {
	          throw new RuntimeException("批量操作数据不可为空 !");
	      }
	      data.forEach((key, value) -> {
	          args.add(key);
	          args.add(value);
	      });
	      return args.toArray();
	  }

}
